package com.colorlight.cloud.gateway.api.message.interceptor.trans.impl;

import com.colorlight.cloud.gateway.api.constants.GatewayConstants;
import com.colorlight.cloud.gateway.api.exception.ReflexException;
import com.colorlight.cloud.gateway.api.message.interceptor.trans.TransFromProtoInterceptor;

import java.lang.reflect.*;
import java.util.*;


/**
 * @author Demon
 * @date 25/12/2023 下午1:46
 */
public class CollectionTransFromProtoInterceptor implements TransFromProtoInterceptor {
	
	private final InterAttributeProcess interEnumProcess =
			new InterEnumProcess();
	private final InterAttributeProcess interTransProcess =
			new InterTransProcess();
	private final InterAttributeProcess interBaseProcess =
			new InterBaseProcess();
	
	@Override
	public Boolean isInterceptor(Class<?> aClass) {
		return List.class.isAssignableFrom(aClass);
	}
	
	@Override
	public void addAttribute(
			Object transObject, Object value, Class<?> inputClass, String methodName) {
		/** 获取方法 */
		Method method = null;
		try {
			/** 这里强依赖了protobuf转的对象 所有集合类型均为Iterable */
			method = transObject.getClass().getMethod(methodName, List.class);
		} catch (NoSuchMethodException e) {
			throw new ReflexException("集合获取方法失败");
		}
		
		/** 多个类型： 与起始入参相同 1.基本类型 2.枚举类型 3.封装类型 */
		Iterable<?> collect = invoke(inputClass).process(value, inputClass);
		// 方法调用
		try {
			method.invoke(transObject, collect);
		} catch (IllegalAccessException | InvocationTargetException e) {
			throw new ReflexException("获取方法失败");
		}
	}
	
	/**
	 * 参数类型转化:反射调用方法入参类型
	 *
	 * @param field 原始参数对象
	 * @return 反射调用方法入参类型
	 * @author Demon
	 * @date 25/12/2023/下午2:41
	 */
	@Override
	public Class<?> getInputClass(Field field) {
		return collectionInternalType(field);
	}
	
	/**
	 * 集合处理 集合类得处理
	 *
	 * @param field 实际属性对象
	 * @return 目标类型集合得内置类型 单层集合
	 * @author Demon
	 * @date 18/12/2023/下午2:34
	 */
	private Class<?> collectionInternalType(Field field) {
		Type genericType = field.getGenericType();
		if (genericType instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) genericType;
			Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
			if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class) {
				return (Class<?>) actualTypeArguments[0];
			}
		}
		throw new ReflexException("集合处理 集合类得处理获取类型异常");
	}
	
	@Override
	public String getProtoMethodName(String name) {
		if (Objects.isNull(name) || name.length() == 0) {
			throw new ReflexException("获取方法名为null");
		}
		return "get" + Character.toUpperCase(name.charAt(0)) + name.substring(1) + "List";
	}
	
	private static class InterEnumProcess implements InterAttributeProcess {
		@Override
		public Iterable<?> process(Object o, Class<?> targetClass) {
			EnumTransFromProtoInterceptor enumTransFromProtoInterceptor =
					(EnumTransFromProtoInterceptor) GatewayConstants.ENUM_TRANS_FROM_PROTO_INTERCEPTOR;
			
			List<?> trans = (List<?>) o;
			List<Object> objectList = new ArrayList<>(trans.size());
			for (Object tmp : trans) {
				objectList.add(enumTransFromProtoInterceptor.enumConversionObject(targetClass, tmp));
			}
			return objectList;
		}
	}
	
	private static class InterBaseProcess implements InterAttributeProcess {
		@Override
		public Iterable<?> process(Object o, Class<?> targetClass) {
			return (List<?>) o;
		}
	}
	
	private static class InterTransProcess implements InterAttributeProcess {
		
		@Override
		public Iterable<?> process(Object o, Class<?> targetClass) {
			ObjectTransFromProtoInterceptor objectTransFromProtoInterceptor =
					(ObjectTransFromProtoInterceptor) GatewayConstants.OBJECT_TRANS_FROM_PROTO_INTERCEPTOR;
			List<?> trans = (List<?>) o;
			List<Object> objectList = new ArrayList<>(trans.size());
			for (Object tmp : trans) {
				objectList.add(objectTransFromProtoInterceptor.protoConversionObject(targetClass, tmp));
			}
			return objectList;
		}
	}
	
	private InterAttributeProcess invoke(Class<?> aClass) {
		
		if (GatewayConstants.OBJECT_TRANS_FROM_PROTO_INTERCEPTOR.isInterceptor(aClass)) {
			return interTransProcess;
		}
		if (GatewayConstants.BASE_TRANS_FROM_PROTO_INTERCEPTOR.isInterceptor(aClass)) {
			return interBaseProcess;
		}
		if (GatewayConstants.ENUM_TRANS_FROM_PROTO_INTERCEPTOR.isInterceptor(aClass)) {
			return interEnumProcess;
		}
		throw new ReflexException("无法转化的Collection类型");
	}
	
	@FunctionalInterface
	interface InterAttributeProcess {
		/**
		 * 参数转化器
		 *
		 * @param o 实际属性
		 * @return 集合参数
		 * @author Demon
		 * @date 21/12/2023/上午9:00
		 */
		Iterable<?> process(Object o, Class<?> targetClass);
	}
}
